package cn.tedu.tmallpassport.service.impl;

import cn.tedu.tmall.common.enumerator.ServiceCode;
import cn.tedu.tmall.common.ex.ServiceException;
import cn.tedu.tmall.common.pojo.authentication.CurrentPrincipal;
import cn.tedu.tmall.common.pojo.po.UserStatePO;
import cn.tedu.tmallpassport.dao.cache.IUserCacheRepository;
import cn.tedu.tmallpassport.dao.persist.repository.impl.UserRepository;
import cn.tedu.tmallpassport.pojo.param.UserLoginInfoParam;
import cn.tedu.tmallpassport.pojo.vo.UserLoginInfoVO;
import cn.tedu.tmallpassport.pojo.vo.UserLoginResultVO;
import cn.tedu.tmallpassport.service.IUserService;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class UserService implements IUserService {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    UserRepository repository;

    @Autowired
    IUserCacheRepository userCacheRepository;

    @Override
    public UserLoginResultVO login(UserLoginInfoParam userLoginInfoParam,String remoteAddr, String userAgent) {
        //用户输入的用户名
        String username = userLoginInfoParam.getUsername();
        //根据用户输入的用户名查询是否有内容
        UserLoginInfoVO loginInfoByUser = repository.getLoginInfoByUsername(username);
        //如果内容为空,则说明用户名不正确
        if (loginInfoByUser == null) {
            String message = "登录失败,用户名密码错误!";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED, message);
        }
        //判断用户的账号是否启用
        if (loginInfoByUser.getEnable() != 1) {
            String message = "登录失败,此账号已经被禁用";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED_DISABLED, message);
        }

        //获取用户输入的密码
        String password = userLoginInfoParam.getPassword();
        //校验密文
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(password, loginInfoByUser.getPassword())) {
            String message = "登录失败,用户名密码错误";
            throw new ServiceException(ServiceCode.ERROR_UNAUTHORIZED, message);
        }


        // TODO 向登录日志表(account_login_log)中插入数据
        // TODO 登录用户名(account_user)中当前用户的相关信息（登录次数、最后登录IP、最后登录时间）

       /* //创建当事人对象
        CurrentPrincipal principal=new CurrentPrincipal();
        principal.setId(loginInfoByUser.getId());
        principal.setUsername(loginInfoByUser.getUsername());

        //获取权限的列表
        ArrayList<SimpleGrantedAuthority> authorities=new ArrayList<>();
        List<String> permissions=loginInfoByUser.getPermissions();
        for (String permission:permissions){
            SimpleGrantedAuthority authority=new SimpleGrantedAuthority(permission);
            authorities.add(authority);
        }

        // 向SecurityContext中存入有效的Authentication
        Authentication authentication=new UsernamePasswordAuthenticationToken(
                principal,"",authorities
        );
        SecurityContext securityContext= SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);*/


        //获取权限的列表
        List<String> permissions = loginInfoByUser.getPermissions();
        String authoritiesJsonString = JSON.toJSONString(permissions);

        UserStatePO userStatePO=new UserStatePO();
        userStatePO.setAuthoritiesJsonString(authoritiesJsonString);
        userStatePO.setEnable(1);

        userCacheRepository.saveUserState(loginInfoByUser.getId(), userStatePO);

        // JWt签名
        String secretKey = "sdasdawdhajsdia/..(*8923-02";

        // 向map添加数据
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", loginInfoByUser.getId());
        claims.put("username", loginInfoByUser.getUsername());
        claims.put("remoteAddr",remoteAddr);
        claims.put("userAgent",userAgent);

        String Jwt = Jwts.builder()
                //header
                .setHeaderParam("alg", "HS252")
                .setHeaderParam("typ", "JWT")
                //Payload
                .setClaims(claims)
                //Verify Signaturt
                .signWith(SignatureAlgorithm.HS256, secretKey)
                //完成
                .compact();

        //返回登录结果
        UserLoginResultVO loginResultVO = new UserLoginResultVO();
        BeanUtils.copyProperties(loginInfoByUser, loginResultVO);
        loginResultVO.setToken(Jwt);
        return loginResultVO;

    }

    // 退出登录
    @Override
    public void logout(CurrentPrincipal currentPrincipal) {
        userCacheRepository.deleteUserState(currentPrincipal.getId());
    }
}
